//IIFE命名空间
(function() {
  //实例化非常牛逼并且非常吊的场景管理器SceneManager，并将它暴露到全局
  var SceneManager = (window.SceneManager = function() {
    //sceneNum代表了当前的场景：1是欢迎界面，2是教程界面，3是开始游戏界面，3是GAMEOVER界面
    this.sceneNum = 1;
    //定义logo图片
    this.logo = game.imgS.logo;
    //play按钮
    this.button_play = game.imgS.button_play;
    this.button_play_Y = myCanvas.height; //按钮从画布下面出现
    this.button_play_X = myCanvas.width / 2 - this.button_play.width / 2;
    //定义logo的y坐标
    this.logoY = -41; //logo从上面往下落
    //定义教程tap按钮
    this.tutorial = game.imgS.tutorial;
    this.tX = myCanvas.width / 2 - this.tutorial.width / 2;
    this.tY = 300;
    this.opacityNumb = 1;
    this.isOpacity = false; //定义透明的闪烁状态
    console.log(this.tX, this.tY);
    //场景管理器负责把管子背景鸟对象添加到game中介者对象中
    game.bird = new Bird();
    game.land = new Land();
    game.backgroun = new Background();
    this.bindEvent();
    //定义管子
  });
  //场景管理器有三个方法，game类的定时器负责来执行update的render， 用户的点击或者鸟死了来执行enter场景的切换
  SceneManager.prototype.update = function() {
    //对场景的编号进行switch判断
    switch (this.sceneNum) {
      //如果是场景1的状态判定更新
      case 1:
        this.logoY += 2; //如果是场景1,那么让logo从上往下的效果，那么每一次的更新都++logY,
        this.button_play_Y -= 9; //那么让button_play从下往上的效果，那么每一次的更新  button_play_Y -=16
        //验收：如果logo的Y值大于了canvas画布的高，那么请你固定到canvas的高
        if (this.logoY > myCanvas.height / 2 - 50) {
          this.logoY = myCanvas.height / 2 - 50;
        }
        //如果button_play_Y小于了 一个值那么请你股固定到这个值
        if (this.button_play_Y < myCanvas.height / 2 + 50) {
          this.button_play_Y = myCanvas.height / 2 + 50;
        }
        break;
      //场景2的业务逻辑
      case 2:
        //教程按钮的闪烁，就是改变opacityNumb，往复闪烁 边界是0.2 和 0.98，到达边界就请返回
        if (!this.isOpacity) {
          this.opacityNumb -= 0.02;
        }
        if (this.isOpacity) {
          this.opacityNumb += 0.02;
        }
        if (this.opacityNumb < 0.02) {
          this.isOpacity = true;
        }
        if (this.opacityNumb > 0.98) {
          this.isOpacity = false;
        }
        break;
      //场景3要进行的对象状态更新
      case 3:
        game.backgroun.update();
        game.land.update();
        game.bird.update();
        game.txtfno -= 0.5; //canvas文字移动速度++
        //如果fno帧编号能被 XXX 取余，就 实例化管子,这样固定一段时间产生新管子（可控）
        //管子的渲染和更新放到SM的render方法中
        if (game.fno % 80 == 0) {
          new Pipe(); //实例化管子后实例化对象就会将自己push到game类的pipeArr数组
        }
        break;
      //场景4 要进行的更新
      case 4:
        this.birdFno++;
        //鸟撞到了管子上那下降
        if (!this.birdLand) {
          //如果非落地状态那么渲染鸟并且下降
          game.bird.y += this.birdFno;
        } else {
        }
        //如果小鸟下降到了 XX值那么就让鸟固定在这个值
        if (game.bird.y >= myCanvas.height * 0.78 - 15) {
          game.bird.y = myCanvas.height * 0.78 - 15;
          //并且把鸟的birdLand（是否已经落地状态）变成true，那么久不会再次下落了
          this.birdLand = true;
        }
        game.ctx.globalAlpha = this.opacityNumb; //改变canvas画布的透明度产生白屏幕效果
        //由于切换到场景四瞬间canvas的透明变0，那么我们让透明度慢慢加回1
        this.opacityNumb += 0.2;
        if (this.opacityNumb > 0.98) {
          this.opacityNumb = 1;
        }

        //从进入场景4开始 每一帧增加birdFno，如果大于60，那么进入场景5
        if (this.birdFno > 60) {
          this.enter(5);
        }
    }
  };
  //渲染场景
  SceneManager.prototype.render = function() {
    //对场景的编号进行switch判断
    switch (this.sceneNum) {
      //如果是场景1,那么canvas画布绘制logo，logo的y是更新后改变的变量
      case 1:
        //场景1，那么渲染背景 大地 和鸟
        game.backgroun.render();
        game.land.render();
        // game.pipeArr
        game.bird.render();
        //把移动的logo画在canvas画布上
        game.ctx.drawImage(
          this.logo,
          myCanvas.width / 2 - this.logo.width / 2,
          this.logoY,
          this.logo.width,
          this.logo.height
        );
        //把移动的this.button_play画在canvas画布上
        game.ctx.drawImage(
          this.button_play,
          this.button_play_X,
          this.button_play_Y,
          this.button_play.width,
          this.button_play.height
        );
        //将咱的小鸟居中
        game.bird.x = myCanvas.width / 2;
        game.bird.y = myCanvas.height - myCanvas.height * 0.65;
        break;
      case 2:
        //场景2，渲染背景 大地 ，煽动翅膀的鸟
        game.backgroun.render();
        game.land.render();
        game.bird.render();
        game.bird.wings();

        //将教程按钮渲染再canvas上
        //闪烁透明度
        game.ctx.save();
        game.ctx.globalAlpha = this.opacityNumb;
        game.ctx.drawImage(
          this.tutorial,
          this.tX,
          this.tY,
          this.tutorial.width,
          this.tutorial.height
        );
        game.ctx.restore();
        break;
      //场景3的渲染
      case 3:
        game.backgroun.render();
        game.land.render();
        //遍历game类的pipeArr，更新并渲染数组中下标i的管子对象和
        for (let i = 0; i < game.pipeArr.length; i++) {
          //判断管子存在于pipearr中那么才进行渲染和更新
          game.pipeArr[i] && game.pipeArr[i].update();
          game.pipeArr[i] && game.pipeArr[i].render();
        }
        //弹幕文字进场
        this.textenter();
        //打印得分,执行game对象的渲染得分方法
        game.scoreGet();
        game.bird.render(); //鸟的渲染
        game.bird.wings(); //鸟的煽动翅膀方法
        break;
      case 4:
        game.backgroun.render();
        game.land.render();
        for (let i = 0; i < game.pipeArr.length; i++) {
          //判断管子存在于pipearr中那么才进行渲染和更新
          game.pipeArr[i] && game.pipeArr[i].render();
        }
        game.scoreGet();
        game.bird.render();
        break;
      //场景5要进行的渲染
      case 5:
        game.backgroun.render();
        game.land.render();
        game.scoreGet();
        //GAME OVER图片的渲染
        game.ctx.drawImage(
          game.imgS.game_over,
          myCanvas.width / 2 - 205 / 2 + 12,
          200,
          205,
          54
        );
        break;
    }
  };
  //enter方法在的执行会将SM对象的场景编号切换为实参，也就是执行enter方法都会切换方法，enter方法控制了切换场景，在enter方法中进行判断每个场景刚进入第一件事要干啥
  SceneManager.prototype.enter = function(num) {
    //将场景编号变为调用这个函数时候的实参
    this.sceneNum = num;
    switch (this.sceneNum) {
      case 1: //场景1
        //分数清空
        game.score = 0;
        break;
      //教程场景
      case 2:
        this.opacityNumb = 1;
        this.text0 = game.txtArr[getRandom(0, 3)];
        this.text1 = game.txtArr[getRandom(0, 3)];
        this.text2 = game.txtArr[getRandom(0, 3)];
        this.text3 = game.txtArr[getRandom(0, 3)];
        break;
      //场景3是play的场景
      case 3:
        //游戏开始先初始化数据 //将游戏帧事件变为，因为鸟的速度还有蚊子浮动的一些速度都是根据帧事件来计算的，所有新的一局游戏都得清空
        game.fno = 0;
        game.bird.fno = 0;
        game.txtfno = myCanvas.width; //将弹幕文字再次移动到初始位置
        game.bird.birdSpeed = 0; //鸟的速度变为初始
        // game.ctx.clearRect(0,0,1000,1000);
        this.birdFno = 0; //进入场景3把鸟的帧数清空
        this.birdLand = false; //场景3新的一局将鸟的是否落地状态变为false
        break;
      case 4:
        //场景四也就是死亡场景，瞬间白一下
        this.opacityNumb = 0;
        break;
    }
  };
  //场景管理器的监听事件，监听来切换场景,需要兼容手机端，那么就要绑定click点击和touch两个事件，点击和触摸的时候都调用咱们定义的Eventhandler函数
  SceneManager.prototype.bindEvent = function() {
    //canvas中是没有dom元素的，不能给img加监听，只能给canvas对象加监听
    var that = this;
    //给canvas添加点击事件，如果场景管理器当前的场景编号是X，那么执行X
    myCanvas.onclick = function(e) {
      //执行我们定义的事件监听handler，并且把鼠标点击时候的事件对象中的鼠标坐标传参进去，Handel会调用这个参数
      that.Eventhandler(e.clientX, e.clientY);
    };
    myCanvas.addEventListener("touchstart", function(e) {
      var touches = e.touches[0]; //事件对象中的touoches触摸对象集合是个类数组，所以要加下标来选择第0个触摸点
      //执行我们定义的事件监听handler，并且把触摸时候的事件对象中的触摸点的坐标传参进去，Handel会调用这个参数
      that.Eventhandler(touches.clientX, touches.clientY);
    });
  };
  //定义触摸和点击监听触发后要调用的函数
  SceneManager.prototype.Eventhandler = function(mouseX, mouseY) {
    var that = this;
    switch (that.sceneNum) {
      //判断，如果是场景1，就执行按钮点击判断，判断成功进入下一个场景2.所有这样就不会进入场景3 4
      case 1:
        var e = e || window.event;
        var mouseX = mouseX - myCanvas.offsetLeft;
        var mouseY = mouseY - myCanvas.offsetTop;
        //判断鼠标位置和button坐标之间的关系，也就是要保证点击的区域是button之内
        if (
          mouseX > that.button_play_X &&
          mouseX < that.button_play_X + that.button_play.width - 10 &&
          mouseY > that.button_play_Y &&
          mouseY < that.button_play_Y + 55
        ) {
          //执行enter，进入场景2
          that.enter(2);
        }
        break;
      //如果在第二个场景，点击会干嘛？切换场景到3
      case 2:
        that.enter(3);
        //清空管子数组
        game.pipeArr = [];
        break;
      //如果在第三个场景，鼠标点击事件变成bird.fly（）飞的函数
      case 3:
        game.bird.fly();
        break;
      //场景5 GAME OVER场景的鼠标点击事件就是回到游戏开始场景1
      case 5:
        this.enter(1);
        break;
    }
  };
  //浮动文字渲染
  SceneManager.prototype.textenter = function() {
    if (game.fno > 100) {
      game.ctx.save();
      game.ctx.fillStyle = bg3();
      game.ctx.fillText(this.text0, game.txtfno, 90);
      game.ctx.restore();
    }

    if (game.fno > 300) {
      game.ctx.save();
      game.ctx.fillStyle = bg3();
      game.ctx.fillText(this.text1, game.txtfno + 150, 155);
      game.ctx.restore();
    }
    if (game.fno > 700) {
      game.ctx.save();
      game.ctx.fillStyle = "purple";
      game.ctx.fillText(
        this.text2,
        game.txtfno + 400,
        myCanvas.height * 0.78 + 50
      );
      game.ctx.restore();
    }
    if (game.fno > 1000) {
      game.ctx.save();
      game.ctx.fillStyle = "darkred";
      game.ctx.fillText(this.text3, game.txtfno + 570, 290);
      game.ctx.restore();
    }
  };
})();
